package io.task.message.socket;

import io.task.message.socket.lock.MapWithLock;
import io.task.message.socket.lock.SetWithLock;
import io.task.message.socket.maintain.*;
import io.task.message.socket.spi.client.ClientConfig;
import io.task.message.socket.spi.server.ServerConfig;
import io.task.message.socket.task.CloseTask;
import io.task.message.socket.task.Handler;
import io.task.message.socket.thread.Threads;
import io.task.message.socket.thread.pool.SynThreadPoolExecutor;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;

import java.nio.ByteOrder;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.atomic.AtomicInteger;

@Slf4j
@Setter
@Getter
public abstract class Config {

    /**
     * 默认的接收数据的buffer size
     */
    public static final int READ_BUFFER_SIZE = Integer.getInteger("tio.default.read.buffer.size", 20480);
    private final static AtomicInteger ID_ATOMIC = new AtomicInteger();
    public static ByteOrder byteOrder = ByteOrder.BIG_ENDIAN;


    /**
     * 本jvm中所有的TioServerConfig对象
     */
    public static final Set<ServerConfig> ALL_SERVER_GROUPCONTEXTS = new HashSet<>();
    /**
     * 本jvm中所有的TioClientConfig对象
     */
    public static final Set<ClientConfig> ALL_CLIENT_GROUPCONTEXTS = new HashSet<>();
    /**
     * 本jvm中所有的TioConfig对象
     */
    public static final Set<Config> ALL_GROUPCONTEXTS = new HashSet<>();
    /**
     * 启动时间
     */
    public long startTime = System.currentTimeMillis();


    /**
     * 心跳超时时间(单位: 毫秒)，如果用户不希望框架层面做心跳相关工作，请把此值设为0或负数
     */
    public long heartbeatTimeout = 1000 * 120;
    /**
     * 解码出现异常时，是否打印异常日志
     */
    public boolean logWhenDecodeError = false;

    /**
     * 接收数据的buffer size
     */
    private int readBufferSize = READ_BUFFER_SIZE;


    public SynThreadPoolExecutor tioExecutor = null;
    public CloseTask closeRunnable;
    public ThreadPoolExecutor groupExecutor = null;
    public ClientNodes clientNodes = new ClientNodes();
    public SetWithLock<ChannelContext> connections = new SetWithLock<ChannelContext>(new HashSet<ChannelContext>());
    public Groups groups = new Groups();
    public Users users = new Users();
    public Tokens tokens = new Tokens();
    public Ids ids = new Ids();
    public BsIds bsIds = new BsIds();
    public Ips ips = new Ips();

    protected String id;
    protected String name = "未命名";

    private boolean isStopped = false;

    public MapWithLock<Integer, Packet> waitingResps = new MapWithLock<Integer, Packet>(new HashMap<Integer, Packet>());

    public Config() {
        this(null, null);
    }


    public Config(SynThreadPoolExecutor tioExecutor, ThreadPoolExecutor groupExecutor) {
        super();
        ALL_GROUPCONTEXTS.add(this);
        if (this instanceof ServerConfig) {
            ALL_SERVER_GROUPCONTEXTS.add((ServerConfig) this);
        } else {
            ALL_CLIENT_GROUPCONTEXTS.add((ClientConfig) this);
        }

        if (ALL_GROUPCONTEXTS.size() > 20) {
            log.warn("已经产生{}个TioConfig对象，t-io作者怀疑你在误用t-io", ALL_GROUPCONTEXTS.size());
        }
        this.id = ID_ATOMIC.incrementAndGet() + "";

        this.tioExecutor = tioExecutor;
        if (this.tioExecutor == null) {
            this.tioExecutor = Threads.getTioExecutor();
        }

        this.groupExecutor = groupExecutor;
        if (this.groupExecutor == null) {
            this.groupExecutor = Threads.getGroupExecutor();
        }

        closeRunnable = new CloseTask(this.tioExecutor);
    }


    public abstract Handler getTioHandler();


    /**
     * 是服务器端还是客户端
     */
    public abstract boolean isServer();


}
